package com.loongtech.core.gen;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.loongtech.core.util.PackageClass;

import freemarker.template.Configuration;
import freemarker.template.Template;

/**
 * 工具类，遍历指定的包，为每一个类生成一个内部类，枚举出所有字段名，包括项目中的父类中的字段
 * @author HivenYang
 *	@date 2014年9月13日
 */
public class GenInnerClassK {

	public static void main(String[] args) {
		GenInnerClassK gen = new GenInnerClassK();
		gen.gen();
	}

	public void gen() {
		System.out.println("开始处理......");
		// 遍历所有class文件，找到有指定注解的类，生成对应的java类
		Set<Class<?>> clazzs = PackageClass.find();
		for(Class<?> clazz : clazzs) {
			if(!clazz.isAnnotationPresent(GenInnerK.class)) continue;
			// 根据类名找到对应的java文件
			String filePackage = clazz.getName();
			filePackage = filePackage.replace(".", "/");
			// 编译后classes路径
			String classpath = GenInnerClassK.class.getClassLoader().getResource("").getPath();
			// maven下java类路径
			String filePath = classpath + "../../src/main/java/" + filePackage + ".java";
			genInnerClassK(filePath, clazz.getName());
		}
		
		System.out.println("处理完毕！");
	}
	
	/**
	 * 根据指定java文件，在文件内生成一个内部类K，列出该类中所有字段的字符串格式字段名
	 * @param filePath
	 * @param pack
	 * @author HivenYang
	 *	@date 2014年12月8日
	 */
	public void genInnerClassK(String filePath, String pack) {
		File file = new File(filePath);
		if(!file.exists()) {
			System.out.println("路径错误，请确定为Maven项目");
			return;
		}

		System.out.println("处理类：" + pack);
		try {
			Class<?> clazz = Class.forName(pack);
			List<String> fieldNames = new ArrayList<>();
			//循环查找所有父类，到Object为止
			while(clazz != Object.class) {
				// 获取本类所有申明过的字段
				Field[] fields = clazz.getDeclaredFields();
				for(Field field : fields) {
					//如果是static的字段就不管
					if((field.getModifiers() & java.lang.reflect.Modifier.STATIC) == java.lang.reflect.Modifier.STATIC) continue;
					fieldNames.add(field.getName());
				}
				clazz = clazz.getSuperclass();
			}
			
			Map<String,Object> map = new HashMap<>();  
			map.put("fields", fieldNames);
			
			//使用freemarker模板拼接内部类
			Configuration configuration = new Configuration();
			//String path = GenInnerClassK.class.getClassLoader().getResource("./templates").getPath();
			String path = GenInnerClassK.class.getResource("").getPath() + "../../../../templates";
			configuration.setDirectoryForTemplateLoading(new File(path));
			Template tpl = configuration.getTemplate("InnerClassK.ftl", "utf-8");
			StringWriter sw = new StringWriter();
			tpl.process(map, sw);
			String innerClassK = sw.getBuffer().toString();
			
			//将生成的内部类拼接在原文件的后面
			@SuppressWarnings("resource")
			BufferedReader br = new BufferedReader(new FileReader(file));
			StringBuilder sb = new StringBuilder();
			String line;
			while((line = br.readLine()) != null) {
				if(line.contains("public static class K")) {
					while(!(line = br.readLine()).contains("}")) {
						continue;
					}
					// 再读一个"}"
					if(!(line = br.readLine()).contains("}")) {
						throw new RuntimeException("生成文件" + pack + "出错！");
					}
					//跳到下一行
					line = br.readLine();
				}
				sb.append(line + "\n");
			}
			br.close();
			
			//去掉java类最后一个大括号，同时添加上内部类
			sb.replace(sb.lastIndexOf("}"), sb.length(), innerClassK + "\n}");

			// 写入java文件
			BufferedWriter bw = new BufferedWriter(new FileWriter(file));
			bw.write(sb.toString());
			bw.flush();
			bw.close();
			
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
}
